#pragma once
#include<iostream>
#include<pthread.h>
#include<queue>
#include<vector>

using namespace std;
class ThreadPool
{
public:
    ThreadPool(int thread_num=5)
    :stopFlag(false)
    {
        _threads.resize(thread_num);
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
        for(int i=0;i<thread_num;i++)
        {
            pthread_create(&_threads[i],nullptr,ThreadFunction,(void*)args);
        }
    }
    void addTask(void(*newTask)(void*),void* args)
    {
        pthread_mutex_lock(&_mutex);
        _taskQueue.push(make_pair(newTask,args));
        //这个时候条件就已经满足了
        pthread_cond_signal(&_cond);
        pthread_mutex_unlock(&_mutex);
    }
    void stop()
    {
        stopFlag=true;
        pthread_cond_broadcast(&_cond);
        for(int i=0;i<_threads.size();i++)
        {
            pthread_join(_threads[i],nullptr);
        }
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }
    ~Thread()
    {
        stop();
    }
private:
    static void* ThreadFunction(void* args)
    {
        ThreadPool* tp=static_cast<ThreadPool*>(args);
        while(!tp->stopFlag)
        {
            pthread_mutex_lock(&_mutex);
            while(tp->_taskQueue.empty() && !tp->stopFlag){
                pthread_cond_wait(&(tp->_cond),&(tp->_mutex));
            }
            if(tp->stopFlag){
                break;
            }
            void (*task)=tp->_taskQueue.front().first;
            void* taskArgs=tp->_taskQueue.front().second;
            pthread_mutex_unlock(&_mutex);
            task(taskArgs);
        }
        return nullptr;
    }
private:
    bool stopFlag;
    vector<pthread_t> _threads;
    queue<void (*)(void*),void* args> _taskQueue;
    pthread_mutex_t _mutex;
    pthread_cond_t _cond;
};

// class ThreadPool
// {
// public:
//     ThreadPool(int thread_num=5):stopFlag(false)
//     {
//         _threads.resize(thread_num);
//         pthread_mutex_init(&_mutex,nullptr);
//         pthread_cond_init(&_cond,nullptr);
//         for(int i=0;i<threads.size();i++)
//         {
//             pthread_create(&threads[i],nullptr,ThreadFunction,this);
//         }
//     }
//     void addTask(void(*newTask)(void*),void* args)
//     {
//         pthread_mutex_lock(&_mutex);
//         _taskQueue
//     }
// private:
//     static void* ThreadFunction(void* args)
//     {

//     }
// private:
//     bool stopFlag;
//     vector<pthread_t> _threads;
//     pthread_mutex_t _mutex;
//     pthread_cond_t _cond;
//     queue<void(*)(void*),void* args> _taskQueue;
// };


// #include <iostream>
// #include <queue>
// #include <pthread.h>
// using namespace std;

// class Mutex
// {
// public:
//     Mutex(pthread_mutex_t* mutex)
//     :_mutex(mutex)
//     {
//         pthread_mutex_init(_mutex,nullptr);
//     }
//     void lock()
//     {
//         pthread_mutex_lock(_mutex);
//     }
//     void unlock()
//     {
//         pthread_mutex_unlock(_mutex);
//     }
//     ~Mutex()
//     {

//     }
// private:
//     pthread_mutex_t* _mutex;
// };
// class LockGuard
// {
// public:
//     LockGuard(pthread_mutex_t* mutex)
//     :_mtx(mutex)
//     {
//         _mtx.lock();
//     }
//     ~LockGuard()
//     {
//         _mtx.unlock();
//     }
// private:
//     Mutex _mtx;
// };

// class ThreadPool {
// public:
//     ThreadPool(int _threadCount=5):stopFlag(false)
//     {
//         threads.resize(_threadCount);
//         pthread_mutex_init(&queueMutex,nullptr);
//         pthread_cond_init(&queueCond,nullptr);
//         for(int i=0;i<_threadCount;i++)
//         {
//             pthread_create(&threads[i],nullptr,ThreadFunction,this);
//         }
//     }
//     ThreadPool(int _threadCount=5):stopFlag(false){
//         threads.resize(_threadCount);
//         pthread_mutex_init(&queueMutex,nullptr);
//         pthread_cond_init(&queueCond,nullptr);
//         for(int i=0;i<_threadCount;i++){
//             pthread_create(&threads[i],nullptr,ThreadFunction,this);
//         }
//     }
//     ThreadPool(int _threadCount=5):stopFlag(false){
//         threads.resize(_threadCount);
//         pthread_mutex_init(&queueMutex,nullptr);
//         pthread_cond_init(&queueCond,nullptr);
//         for(int i=0;i<_threadCount;;i++){
//             //首元素代表线程的标识符
//             pthread_create(&threads[i],nullptr,threadFunction,this);
//         }
//     }
//     ThreadPool(int _threadCount=5):stopFlag(false){
//         threads.resize(_threadCount);
//         pthread_mutex_init(&queueMutex,nullptr);
//         pthread_cond_init(&queueCond,nullptr);
//         for(int i=0;i<_threadCount;i++){
//             //这里的工作函数是一个静态函数，为了能够让这个静态函数访问类内的成员变量和函数所以
//             //这里选择传入this指针
//             pthread_create(&threads[i],nullptr,threadFunction,this);
//         }
//     }
//     ThreadPool(int _threadCount = 5) : stopFlag(false) {
//         threads.resize(_threadCount);
//         pthread_mutex_init(&queueMutex, NULL);
//         pthread_cond_init(&queueCond, NULL);
//         for (int i = 0; i < _threadCount; i++) {
//             pthread_create(&threads[i], NULL, threadFunction, this);
//         }
//     }
//     //线程池当中的任务就是将工作函数添加到某一个队列当中供某个线程使用
//     void addTask(void (*newTask)(void*),void* args){
//         pthread_mutex_lock(&queueMutex);
//         taskQueue.push(make_pair(newTask,arg));
//         pthread_cond_signal(&queueCond);
//         pthread_mutex_unlock(&queueMutex);
//     }
//     void addTask(void (*newTask)(void*),void* arg)
//     {
//         LockGuard lockguard(&queueMutex);
//         //将一个函数指针以及这个指针的参数传递过去
//         taskQueue.push(make_pair(newTask,arg));
//         pthread_cond_signal(&queueCond);
//     }
//     void addTask(void (*newTask)(void*),void* arg){
//         pthread_mutex_lock(&queueMutex);
//         taskQueue.push(make_pair(newTask,arg));
//         pthread_cond_signal(&queueCond);
//         pthread_mutex_unlock(&queueMutex);
//     }
//     void addTask(void (*newTask)(void *), void *arg) {
//         pthread_mutex_lock(&queueMutex);
//         taskQueue.push(make_pair(newTask, arg));
//         pthread_cond_signal(&queueCond);
//         pthread_mutex_unlock(&queueMutex);
//     }

//     void Stop()
//     {
//         stopFlag=true;
//         pthread_cond_broadcast(&queueCond);
//         for(int i=0;i<threads.size();i++)
//         {
//             pthread_join(threads[i],nullptr);
//         }
//         pthread_cond_destroy(&queueCond);
//         pthread_mutex_destroy(&queueMutex);
//     }
//     void stop()
//     {
//         stopFlag=true;
//         pthread_cond_broadcast(&queueCond);
//         for(int i=0;i<threads.size();i++)
//         {
//             pthread_join(threads[i],nullptr);
//         }
//         //当退出以后锁这些东西就可以释放了
//         pthread_cond_destroy(&queueCond);
//         pthread_mutex_destroy(&queueMutex);
//     }
//     void stop()
//     {
//         stopFlag=true;
//         pthread_cond_broadcast(&queueCond);
//         for(int i=0;i<threads.size();i++){
//             pthread_join(threads[i],nullptr);
//         }
//         pthread_mutex_destroy(&queueMutex);
//         pthread_cond_destroy(&queueCond);
//     }
//     void stop() {
//         stopFlag = true;
//         pthread_cond_broadcast(&queueCond);
//         for (int i = 0; i < threads.size(); i++) {
//             pthread_join(threads[i], NULL);
//         }
//         pthread_cond_destroy(&queueCond);
//         pthread_mutex_destroy(&queueMutex);
//     }
//     ~ThreadPool()
//     {
//         stop();
//     }
//     ~ThreadPool() {
//         stop();
//     }

// private:
//     static void* ThreadFunction(void* args)
//     {
//         ThreadPool* poolptr=static_cast<ThreadPool*>(args);
//         while(!poolptr->stopFlag)
//         {
//             LockGuard lockguard(&queueMutex);
//             while(poolptr->taskQueue.empty() && !poolptr->stopFlag)
//             {
//                 pthread_cond_wait(&(poolptr->queueCond),&(poolptr->queueMutex));
//             }
//             //这个时候线程池就要回收了
//             if(poolptr->stopFlag)
//             {
//                 break;
//             }
//             void (*task)(void*)=poolptr->taskQueue.front().first;
//             void* taskArg=poolptr->taskQueue.front().second;
//             poolptr->taskQueue.pop();
//         }
//     }
//     static void* ThreadFunction(void* args)
//     {
//         ThreadPool* poolptr=static_cast<ThreadPool*>(args);
//         while(poolptr->stopFlag)
//         {
//             pthread_mutex_lock(&(poolptr->queueMutex));
//             while(poolptr->taskQueue.empty() && !poolptr->stopFlag){
//                 pthread_cond_wait(&(poolptr->queueCond),&(poolptr->taskQueue));
//             }
//             if(poolptr->stopFlag){
//                 break;
//             }
//             void (*task)(void*)=poolptr->taskQueue.front().first;
//             void* taskArg=poolptr->taskQueue.front().second;
//             poolptr->taskQueue.pop();
//             pthread_mutex_unlock(&(poolptr->queueMutex));
//             return nullptr;
//         }
//     }
//     static void* threadFunction(void* args)
//     {
//         ThreadPool* poolptr=static_cast<ThreadPool*>(args);
//         while(poolptr->taskQueue.empty() && !poolptr->stopFlag){
//             pthread_cond_wait(&(poolptr->queueCond),&(poolptr->queueMutex));
//         }
//         if(poolptr->stopFlag){
//             break;
//         }
//         void (*task)(void*)=poolptr->taskQueue.front().first;
//         void* taskArg=poolptr->taskQueue.front().second;
//         poolptr->taskQueue.pop();
//         pthread_mutex_unlock(&poolptr->queueMutex);
//         return nullptr;
//     }
//     static void* threadFuntion(void* args)
//     {
//         //因为我们想要让这个静态的函数访问这个线程池内部的变量或者函数，就需要使用指针的类型转换
//         ThreadPool* poolptr=static_cast<ThreadPool*>(args);
//         while(!poolptr->stopFlag)
//         {
//             pthread_mutex_lock(&(poolptr->queueMutex));
//             //如果这个任务队列为空的时候就必须等待
//             while(poolptr->taskQueue.empty() && !poolptr->stopFlag)
//             {
//                 pthread_cond_wait(&(poolptr->queueCond),&(poolptr->queueMutex));
//             }
//             //如果控制变量不符合也不可以运行
//             if(poolptr->stopFlag)
//             {
//                 break;
//             }
//             void (*task)(void*)=poolptr->taskQueue.front().first;
//             void* taskArg=poolptr->taskQueue.front().second;
//             poolptr->taskQueue.pop();
//             pthread_mutex_unlock(&(poolptr->queueMutex));
//         }
//         return nullptr;
//     }
//     static void *threadFunction(void *arg) {
//         ThreadPool *poolPtr = static_cast<ThreadPool *>(arg);
//         while (!poolPtr->stopFlag) {
//             pthread_mutex_lock(&(poolPtr->queueMutex));
//             while (poolPtr->taskQueue.empty() && !poolPtr->stopFlag) {
//                 pthread_cond_wait(&(poolPtr->queueCond), &(poolPtr->queueMutex));
//             }
//             if (poolPtr->stopFlag) {
//                 break;
//             }
//             void (*task)(void *) = poolPtr->taskQueue.front().first;
//             void *taskArg = poolPtr->taskQueue.front().second;
//             poolPtr->taskQueue.pop();
//             pthread_mutex_unlock(&(poolPtr->queueMutex));
//             task(taskArg);
//         }
//         return NULL;
//     }

// private:
//     vector<pthread_t> threads;
//     queue<pair<void (*)(void *), void *> > taskQueue;
//     pthread_mutex_t queueMutex;
//     pthread_cond_t queueCond;
//     bool stopFlag;
// private:
// //将线程的标识符放入vector容器当中
//     vector<pthread_t> threads;
//     //这个任务队列里面要存放一个函数指针（工作参数），以及工作参数的参数
//     queue<pair<void(*)(void*),void*>> taskQueue;
//     pthread_mutex_t queueMutex;
//     pthread_cond_t queueCond;
//     bool stopFlag;
// };